function htmlParse(html) {
  const stack = []; // 管理节点嵌套关系
  const root = { type: "document", children: [] }; // 根节点
  let currentParent = root; // 当前父节点
  let index = 0; // 当前解析位置

  // 正则表达式匹配标签、属性和内容
  const tagReg = /<(\/?)([a-zA-Z][^\s>]*)([\s\S]*?)>|([^<]+)/g;
  const attrReg =
    /([a-z][a-z0-9_-]*)(?:\s*=\s*(?:(['"])(.*?)\2|([^\s'">]+)))?/g;
  const selfCloseTags = new Set(["img", "input", "br", "meta", "link"]);

  // 辅助函数：解析属性字符串
  function parseAttrs(attrStr) {
    const attrs = {};
    let match;
    while ((match = attrReg.exec(attrStr)) !== null) {
      const name = match[1];
      // 属性值（优先使用带引号的值）
      const value =
        match[3] !== undefined
          ? match[3]
          : match[4] !== undefined
            ? match[4]
            : "";
      attrs[name] = value;
    }
    return attrs;
  }

  // 主解析循环
  while (index < html.length) {
    tagReg.lastIndex = index;
    const match = tagReg.exec(html);
    if (!match) break; // 无更多匹配项

    const [fullMatch, closeSlash, tagName, restAttrs, textContent] = match;
    index = tagReg.lastIndex; // 更新解析位置

    if (textContent) {
      // 处理文本节点
      const text = textContent.trim();
      if (text) {
        currentParent.children.push({
          type: "text",
          content: text,
        });
      }
    } else if (closeSlash) {
      // 处理闭合标签
      if (currentParent.tagName === tagName) {
        currentParent = stack.pop(); // 弹出栈，返回父级
      }
    } else {
      // 处理开始标签
      const isSelfClose = selfCloseTags.has(tagName) || restAttrs.endsWith("/");
      const attrs = parseAttrs(restAttrs.replace(/\s*\/$/, "")); // 移除尾部'/'

      const node = {
        type: "element",
        tagName: tagName.toLowerCase(), // 标签名小写
        attributes: attrs,
        children: [],
      };

      currentParent.children.push(node);
      if (!isSelfClose) {
        // 非自闭合标签入栈，成为当前父级
        stack.push(currentParent);
        currentParent = node;
      }
    }
  }

  return root.children;
}

export { htmlParse };
